package p.ithorns.framework.web.interceptor;


import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import p.ithorns.framework.core.exception.BizException;

import javax.servlet.http.HttpServletRequest;
import java.io.Serializable;
import java.io.UnsupportedEncodingException;
import java.lang.reflect.Field;
import java.net.URLDecoder;
import java.net.URLEncoder;
import java.nio.charset.StandardCharsets;
import java.util.Enumeration;
import java.util.HashMap;
import java.util.Map;

/**
 * RequestHeaderContext
 *
 * @author Ht.L
 * @date 2023-05-26 18:37
 * @since 1.0.0
 */
public class RequestHeaderContext {

    private final static Logger log = LoggerFactory.getLogger(RequestHeaderContext.class);

    private static final String charset = StandardCharsets.UTF_8.name();

    private static final ThreadLocal<RequestHeader> CONTEXT_THREAD_LOCAL = new ThreadLocal<>();

    private static final Map<String, Field> FIELD_MAP = new HashMap<>();

    static {
        synchronized (FIELD_MAP) {
            Field[] declaredFields = RequestHeader.class.getDeclaredFields();
            for (Field field : declaredFields) {
                field.setAccessible(true);
                // Header被tomcat转成小写了，所以这里也要转成小写
                FIELD_MAP.put(field.getName().toLowerCase(), field);
            }
        }
    }

    public static void build(HttpServletRequest request) {
        Enumeration<String> headerNames = request.getHeaderNames();
        RequestHeader headers = new RequestHeader();
        while (headerNames.hasMoreElements()) {
            String headerName = headerNames.nextElement();
            String headerValue = request.getHeader(headerName);
            Field field = FIELD_MAP.get(headerName);
            if (null != field) {
                try {
                    String decodeValue = URLDecoder.decode(headerValue, charset);
                    field.set(headers, decodeValue);
                } catch (IllegalAccessException e) {
                    log.warn(e.getMessage());
                } catch (UnsupportedEncodingException e) {
                    log.error("Header解码失败: {}", e.getMessage());
                    throw new BizException(e.getMessage());
                }
            }
        }
        CONTEXT_THREAD_LOCAL.set(headers);
    }


    public static RequestHeader get() {
        return CONTEXT_THREAD_LOCAL.get();
    }

    public static String getEmpCode() {
        return get().getEmpCode();
    }

    public static void clean() {
        CONTEXT_THREAD_LOCAL.remove();
    }


    public static final class RequestHeader implements Serializable {

        /**
         * 租户ID
         */
        private String tenantId;

        /**
         * 组织编码
         */
        private String orgCode;

        /**
         * 人员编码
         */
        private String empCode;

        /**
         * 用户id
         */
        private String accountId;

        /**
         * 人员名称
         */
        private String empName;

        /**
         * token
         */
        private String token;

        private RequestHeader() {}

        public String getTenantId() {
            return tenantId;
        }

        public String getOrgCode() {
            return orgCode;
        }

        public String getEmpCode() {
            return empCode;
        }

        public String getAccountId() {
            return accountId;
        }

        public String getEmpName() {
            return empName;
        }

        public String getToken() {
            return token;
        }

        public void setTenantId(String tenantId) {
            this.tenantId = tenantId;
        }

        public void setOrgCode(String orgCode) {
            this.orgCode = orgCode;
        }

        public void setEmpCode(String empCode) {
            this.empCode = empCode;
        }

        public void setAccountId(String accountId) {
            this.accountId = accountId;
        }

        public void setEmpName(String empName) {
            this.empName = empName;
        }

        public void setToken(String token) {
            this.token = token;
        }
    }


    public static void main(String[] args) throws UnsupportedEncodingException {
        String code = "楼海涛";

        String encode = URLEncoder.encode(code, StandardCharsets.UTF_8.name());
        System.out.println(encode);

        String decode  = URLDecoder.decode(encode, StandardCharsets.UTF_8.name());
        System.out.println(decode);
    }
}